package com.tjvib.view.fragment;

import static android.app.Activity.RESULT_OK;

import static com.tjvib.Constants.SUCCESS;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;

import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.tjvib.R;
import com.tjvib.adapter.DatasetAdapter;
import com.tjvib.base.BaseFragment;
import com.tjvib.bean.DataSet;
import com.tjvib.bean.DataSetInfo;
import com.tjvib.common.Callback;
import com.tjvib.event.PayResultEvent;
import com.tjvib.sensor.LocalSensorData;
import com.tjvib.sensor.LpmsB2SensorData;
import com.tjvib.util.FileUtil;
import com.tjvib.util.LogUtil;
import com.tjvib.util.Manager.DataSetManager;
import com.tjvib.util.Manager.UserManager;
import com.tjvib.util.PayUtil;
import com.tjvib.util.ToastUtil;
import com.tjvib.util.retrofit.BaseResponse;
import com.tjvib.util.retrofit.RetrofitHelper;
import com.tjvib.view.activity.AnalysisMethodActivity;
import com.tjvib.view.activity.InterceptActivity;
import com.tjvib.view.dialog.HintDialog;
import com.tjvib.view.dialog.LoadingDialog;
import com.tjvib.widget.AndroidScheduler;
import com.tjvib.widget.SlideRecyclerView;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import pub.devrel.easypermissions.EasyPermissions;

public class DatasetFragment extends BaseFragment implements EasyPermissions.PermissionCallbacks {

    private SlideRecyclerView frag_dataset_srv;
    private FloatingActionButton frag_dataset_fbtn_add;
    private TextView frag_dataset_tv_hint;

    private DatasetAdapter datasetAdapter;
    private List<DataSetInfo> datasetBeanList = new ArrayList<>();
    private Uri fileUri;

    String[] perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    int RC_READ_AND_WRITE_EXTERNAL_STORAGE = 56;

    public BottomDatasetDialog bottomDatasetDialog;

    @Override
    protected int getContentView() {
        return R.layout.fragment_dataset;
    }

    @Override
    public void onResume() {
        super.onResume();
        updateDataListBackground();
    }


    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        // 权限请求成功回调
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        // 权限请求失败回调
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            // 用户拒绝权限并勾选了不再询问
            // 引导用户去设置页面手动开启权限
            ToastUtil.show("请您前往本手机设置手动开启权限");
        }
    }

    @Override
    protected void initView() {
        if (!EasyPermissions.hasPermissions(getActivity(), perms)) {
            EasyPermissions.requestPermissions(getActivity(), "请授予APP读写存储卡权限", RC_READ_AND_WRITE_EXTERNAL_STORAGE, perms);
//            Alerter.create(getActivity()).setTitle("存储权限说明").setText("用于读取传感器数据集并分享").show();
        }

        updateDataList();

        frag_dataset_srv = getView().findViewById(R.id.frag_dataset_srv);

        frag_dataset_fbtn_add = getView().findViewById(R.id.frag_dataset_fbtn_add);
        frag_dataset_fbtn_add.setOnClickListener(v -> {
            if (EasyPermissions.hasPermissions(getActivity(), perms)) {
                Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
                chooseFile.setType("*/*");
                chooseFile.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
                startActivityForResult(Intent.createChooser(chooseFile, "选择一个csv数据文件"), 2);
            }else{
                EasyPermissions.requestPermissions(getActivity(), "请授予APP读写存储卡权限", RC_READ_AND_WRITE_EXTERNAL_STORAGE, perms);
            }
        });

        frag_dataset_tv_hint = getView().findViewById(R.id.frag_dataset_tv_hint);
    }

    @Override
    protected void initData() {
        bottomDatasetDialog = new BottomDatasetDialog(getView().getContext(), R.style.DialogTheme);

        datasetAdapter = new DatasetAdapter(R.layout.item_dataset, datasetBeanList, getView().getContext(), DatasetFragment.this);

        frag_dataset_srv.setLayoutManager(new LinearLayoutManager(getView().getContext()));
        LinearSnapHelper snapHelper = new LinearSnapHelper();
        snapHelper.attachToRecyclerView(frag_dataset_srv);
        frag_dataset_srv.setAdapter(datasetAdapter);

        if (datasetBeanList != null && datasetBeanList.size() != 0)
            frag_dataset_tv_hint.setVisibility(View.INVISIBLE);
        else
            frag_dataset_tv_hint.setVisibility(View.VISIBLE);
    }

    public void showDeleteDataSetDialog(DataSetInfo dataSet) {
        getActivity().runOnUiThread(() -> {
            HintDialog hintDialog = new HintDialog(getActivity());
            hintDialog.showDialog(getActivity(), "警告",
                    "删除数据后将不可恢复，如果您已购买该数据的分析权限，请谨慎操作",
                    view -> {
                        deleteDataSet(dataSet);
                        hintDialog.dismiss();
                    },
                    view -> hintDialog.dismiss());
        });
    }

    private void deleteDataSet(DataSetInfo dataSet) {
        LoadingDialog loadingDialog = new LoadingDialog(getActivity());
        loadingDialog.showDialog(getActivity(), "正在删除数据…");
        RetrofitHelper.getInstance().create()
                .delete(String.valueOf(UserManager.getInstance().getUserId()), String.valueOf(dataSet.getId()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidScheduler.mainThread())
                .subscribe(new Observer<BaseResponse>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BaseResponse value) {
                        loadingDialog.dismiss();
                        if (value.getCode() == SUCCESS) {
                            frag_dataset_srv.closeMenu();
                            ToastUtil.show(value.getMessage());
                            datasetBeanList.remove(dataSet);
                            datasetAdapter.notifyDataSetChanged();
                        } else {
                            showErrorDialog(value.getMessage());
                        }
                        updateDataListBackground();
                    }

                    @Override
                    public void onError(Throwable e) {
                        loadingDialog.dismiss();
                        showErrorDialog(e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    public void updateDataList() {
        LoadingDialog loadingDialog = new LoadingDialog(getContext());
        loadingDialog.showDialog(getActivity(), "正在加载数据…");
        RetrofitHelper.getInstance().create()
                .getDataSetsInfoList(String.valueOf(UserManager.getInstance().getUserId()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidScheduler.mainThread())
                .subscribe(new Observer<BaseResponse>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BaseResponse value) {
                        LogUtil.i("updateDataList "+value.getCode() + "\n" + value.getMessage() + "\n" + value.getData());
                        loadingDialog.dismiss();
                        if (value.getCode() == SUCCESS) {
                            try {
                                JSONArray jsonArray = new JSONArray("" + value.getData());
                                datasetBeanList.clear();
                                for (int i = 0; i < jsonArray.length(); i++) {
                                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                                    DataSetInfo info = new DataSetInfo(jsonObject.toString());
                                    datasetBeanList.add(info);
                                }
                                datasetAdapter.notifyDataSetChanged();
                                if (datasetBeanList != null)
                                    frag_dataset_tv_hint.setVisibility(View.GONE);
                            } catch (JSONException e) {
                                LogUtil.e("e=" + e.getMessage());
                            }
                        } else {
                            showErrorDialog(value.getMessage());
                            LogUtil.e(value.getMessage() + value.getData());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        loadingDialog.dismiss();
                        LogUtil.e("e=" + e.getMessage());
                        ToastUtil.show(e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    public void updateDataListBackground() {
        RetrofitHelper.getInstance().create()
                .getDataSetsInfoList(String.valueOf(UserManager.getInstance().getUserId()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidScheduler.mainThread())
                .subscribe(new Observer<BaseResponse>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BaseResponse value) {
                        if (value.getCode() == SUCCESS) {
                            try {
                                JSONArray jsonArray = new JSONArray("" + value.getData());
                                datasetBeanList.clear();
                                for (int i = 0; i < jsonArray.length(); i++) {
                                    HashMap<String, String> item = new HashMap<>();
                                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                                    DataSetInfo info = new DataSetInfo(jsonObject.toString());
                                    datasetBeanList.add(info);
                                }
                                datasetAdapter.notifyDataSetChanged();
                                if (datasetBeanList != null)
                                    frag_dataset_tv_hint.setVisibility(View.GONE);
                            } catch (JSONException e) {
                                LogUtil.e("e=" + e.getMessage());
                            }
                        } else {
                            showErrorDialog(value.getMessage());
                            LogUtil.e(value.getMessage() + value.getData());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        LogUtil.e("e=" + e.getMessage());
                        ToastUtil.show(e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    private void exportDataSet(DataSetInfo dataSetInfo, Callback callback) {
        LoadingDialog loadingDialog = new LoadingDialog(getActivity());
        loadingDialog.showDialog(getActivity(), "正在导出，请稍后…");
        RetrofitHelper.getInstance().create()
                .getDataSetContent(String.valueOf(UserManager.getInstance().getUserId()), String.valueOf(dataSetInfo.getId()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidScheduler.mainThread())
                .subscribe(new Observer<BaseResponse>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BaseResponse value) {
                        if (value.getCode() == SUCCESS) {
                            doExport(dataSetInfo, String.valueOf(value.getData()), callback);
                        } else {
                            showErrorDialog("数据获取失败");
                        }
                        loadingDialog.dismiss();
                    }

                    @Override
                    public void onError(Throwable e) {
                        loadingDialog.dismiss();
                        showErrorDialog(e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    private void doExport(DataSetInfo info, String content, Callback callback) {
        try {
            JSONArray contentArray = new JSONArray(content);
            if (info.getType().equals("local")) {
                List<LocalSensorData> contentList = new ArrayList<>();
                for (int i = 0; i < contentArray.length(); i++) {
                    JSONObject dataObject = contentArray.getJSONObject(i);
                    LocalSensorData item = new LocalSensorData(dataObject);
                    contentList.add(item);
                }

                DataSet<LocalSensorData> dataSet = new DataSet<>(info, contentList);
                FileUtil.exportToCsv(getContext(), dataSet, callback);
            } else if (info.getType().equals("lpmsb2")) {
                List<LpmsB2SensorData> contentList = new ArrayList<>();
                for (int i = 0; i < contentArray.length(); i++) {
                    JSONObject dataObject = contentArray.getJSONObject(i);
                    LpmsB2SensorData item = new LpmsB2SensorData(dataObject);
                    contentList.add(item);
                }

                DataSet<LpmsB2SensorData> dataSet = new DataSet<>(info, contentList);
                FileUtil.exportToCsv(getContext(), dataSet, callback);
            }
        } catch (JSONException e) {
            showErrorDialog("服务器数据解析失败：" + e.getMessage());
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Pattern p = Pattern.compile(".+(.csv|.CSV)$");
            fileUri = data.getData();
            String fileUriStr = fileUri.toString();
            File file = new File(fileUriStr);
            String displayName = "";
            if (fileUriStr.startsWith("content://")) {
                Cursor cursor = null;
                try {
                    cursor = getActivity().getContentResolver().query(fileUri, null, null, null, null);
                    if (cursor != null && cursor.moveToFirst()) {
                        displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                    }
                } finally {
                    cursor.close();
                }
            } else if (fileUriStr.startsWith("file://")) {
                displayName = file.getName();
            }

            Matcher m = p.matcher(displayName);
            if (m.find()) {
                ProgressDialog progressDialog = new ProgressDialog(getContext());
                progressDialog.setCanceledOnTouchOutside(false);
                progressDialog.setMessage("正在导入...");
                progressDialog.show();
                FileUtil.importFromCsv(getContext(), fileUri, displayName.replace(".csv", ""), new Callback() {
                    @Override
                    public void onSuccess(String message, String data) {
                        progressDialog.dismiss();
                        updateDataList();
                    }

                    @Override
                    public void onFail(String message, String data) {
                        progressDialog.dismiss();
                        showErrorDialog(message);
                    }

                    @Override
                    public void onError(String message, String data) {
                        progressDialog.dismiss();
                        showErrorDialog(message);
                    }
                });
            } else
                showErrorDialog("请选择csv格式数据文件！");
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onPayResultEvent(PayResultEvent event) {
        switch (event.getStatus()) {
            case PayResultEvent.STATUS_FAILURE:
                showErrorDialog(event.getMessage());
                break;
            default:
                showHintDialog(event.getMessage());
                break;
        }
    }


    public class BottomDatasetDialog extends BottomSheetDialog {
        public BottomDatasetDialog(@NonNull Context context, int themeResId) {
            super(context, themeResId);
        }

        public void showBottomDialog(Context context, DataSetInfo dataSetInfo) {
            View view = LayoutInflater.from(context).inflate(R.layout.dialog_bottom_dataset, null);
            this.setContentView(view);
            this.setCanceledOnTouchOutside(true);
            this.show();

            this.findViewById(R.id.dialog_bot_dataset_tv_open).setOnClickListener(view0 -> {
                if (!EasyPermissions.hasPermissions(getActivity(), perms)) {
                    EasyPermissions.requestPermissions(getActivity(), "请授予APP读写存储卡权限", RC_READ_AND_WRITE_EXTERNAL_STORAGE, perms);
//                    Alerter.create(getActivity()).setTitle("存储权限说明").setText("用于读取传感器数据集并分享").show();
                }
                if (EasyPermissions.hasPermissions(getActivity(), perms)) {
                    if (FileUtil.isCsvExists(getContext(), dataSetInfo.getName())) {
                        FileUtil.openDataSetFile(getContext(), dataSetInfo.getName(), new Callback() {
                            @Override
                            public void onSuccess(String message, String data) {
                            }

                            @Override
                            public void onFail(String message, String data) {
                                showErrorDialog("打开失败：" + message);
                            }

                            @Override
                            public void onError(String message, String data) {
                                showErrorDialog("打开失败：" + message);
                            }
                        });
                    } else {
                        exportDataSet(dataSetInfo, new Callback() {
                            @Override
                            public void onSuccess(String message, String data) {
                                //showHintDialog("已成功导出到 内部存储/Android/data/com.tjvib/files/datasets/ 目录下");
                                FileUtil.openDataSetFile(getContext(), dataSetInfo.getName(), new Callback() {
                                    @Override
                                    public void onSuccess(String message, String data) {
                                    }

                                    @Override
                                    public void onFail(String message, String data) {
                                        showErrorDialog("打开失败：" + message);
                                    }

                                    @Override
                                    public void onError(String message, String data) {
                                        showErrorDialog("打开失败：" + message);
                                    }
                                });
                            }

                            @Override
                            public void onFail(String message, String data) {
                                showErrorDialog("打开失败" + (message.isEmpty() ? "" : " : " + message));
                            }

                            @Override
                            public void onError(String message, String data) {
                                showErrorDialog("打开失败" + (message.isEmpty() ? "" : " : " + message));
                            }
                        });
                    }
                    dismiss();
                }
            });

            this.findViewById(R.id.dialog_bot_dataset_tv_anal).setOnClickListener(view1 -> {
                if (dataSetInfo.isAnalyzable()) {
                    DataSetManager.getInstance().setDataSetInfo(dataSetInfo);
                    startActivity(new Intent(getContext(), AnalysisMethodActivity.class));
                } else {
                    showPermissionNotAllowedDialog(getActivity(), dataSetInfo.getId());
                }
                dismiss();
            });

            this.findViewById(R.id.dialog_bot_dataset_tv_share).setOnClickListener(view12 -> {
                dismiss();
                if (!EasyPermissions.hasPermissions(getActivity(), perms)){
                    EasyPermissions.requestPermissions(getActivity(), "请授予APP读写存储卡权限", RC_READ_AND_WRITE_EXTERNAL_STORAGE, perms);
//                    Alerter.create(getActivity()).setTitle("存储权限说明").setText("用于读取传感器数据集并分享").show();
                }
                if (EasyPermissions.hasPermissions(getActivity(), perms)) {
                    if (FileUtil.isCsvExists(getContext(), dataSetInfo.getName())) {
                        FileUtil.shareDataSetFile(getActivity(), dataSetInfo.getName());
                    } else {
                        exportDataSet(dataSetInfo, new Callback() {
                            @Override
                            public void onSuccess(String message, String data) {
                                FileUtil.shareDataSetFile(getActivity(), dataSetInfo.getName());
                            }

                            @Override
                            public void onFail(String message, String data) {
                                showErrorDialog("打开失败" + (message.isEmpty() ? "" : " : " + message));
                            }

                            @Override
                            public void onError(String message, String data) {
                                showErrorDialog("打开失败" + (message.isEmpty() ? "" : " : " + message));
                            }
                        });
                    }
                }
            });

            this.findViewById(R.id.dialog_bot_dataset_tv_cancel).setOnClickListener(view13 -> dismiss());
        }


        private void showPermissionNotAllowedDialog(Context context, long dataSetId) {
            HintDialog hintDialog = new HintDialog(context);
            hintDialog.showDialog(context, "提示", "当前未获得此数据集的分析权限，是否前往购买？",
                    view -> {
                        showBalanceDialog(UserManager.getInstance().getAnalysisTrial(), dataSetId);
                        hintDialog.dismiss();
                    },
                    view -> hintDialog.dismiss());
        }


        private void showBalanceDialog(int trial, long dataSetId) {
            String hint;
            int target;
            if (UserManager.getInstance().isVip()) {
                requestAnalysis(dataSetId);
                return;
            }

            if (trial > 0) {
                hint = "本次使用一次，是否继续？";
                target = 0;
            } else {
                hint = "分析次数用尽，是否前往充值？";
                target = 1;
            }

            String message = "剩余分析次数：" + trial + "\n" + hint;
            HintDialog hintDialog = new HintDialog(getActivity());
            hintDialog.showDialog(getActivity(), "提示", message,
                    view -> {
                        switch (target) {
                            case 0:
                                requestAnalysis(dataSetId);
                                break;
                            case 1:
                                PayUtil.showProductDialog(DatasetFragment.this);
                                break;
                        }
                        hintDialog.dismiss();
                    },
                    view -> hintDialog.dismiss());
        }


        private void requestAnalysis(long dataSetId) {
            RetrofitHelper.getInstance().create()
                    .analyse(String.valueOf(UserManager.getInstance().getUserId()), String.valueOf(dataSetId))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidScheduler.mainThread())
                    .subscribe(new Observer<BaseResponse>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(BaseResponse value) {
                            LogUtil.e("requestAnalysis "+value.getCode()+" "+ value.getMessage()+" "+value.getData());
                            if (value.getCode() == SUCCESS) {
                                showHintDialog(value.getMessage());
                                UserManager.getInstance().setInfo(String.valueOf(value.getData()));
                                updateDataList();
                            } else {
                                showErrorDialog(value.getMessage());
                            }
                        }

                        @Override
                        public void onError(Throwable e) {
                            showErrorDialog(e.getMessage());
                        }

                        @Override
                        public void onComplete() {

                        }
                    });
        }
    }
}